/*
 *	process.c
 *
 *	sglib.lib
 *
 *	Audio Finger Print project
 */

#define _CRT_SECURE_NO_WARNINGS

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "..\fftrun\window.h"
#include "..\fftrun\fftrun.h"
#include "..\waveio\wave.h"
#include "spectrogram.h"

#define WAV_RECONSTRUCT 0
#define TXT_RECORD		0

static WAVE wave;

// input/output buffers - SG_INOUT_SIZE
static __int16 bufIn[SG_INOUT_SIZE];
static __int16 bufOut[SG_INOUT_SIZE];

// overlapped buffers - SG_INOUT_SIZE*WINDOW_OVERLAP=SG_FFT_SIZE
static float bufProc[SG_INOUT_SIZE*SG_WINDOW_OVERLAP];
//static float win[SG_INOUT_SIZE*SG_WINDOW_OVERLAP];
static float buff_forward[SG_INOUT_SIZE*SG_WINDOW_OVERLAP];

#if WAV_RECONSTRUCT
static float buff_backward[SG_INOUT_SIZE*SG_WINDOW_OVERLAP];
#endif

static SPECTROGRAM spectrogram;

void SG_ProcessFile(char* name)
{
	FILE* fin;
	FILE* fbin;
#if TXT_RECORD
	FILE* ftxt;
    int i;
#endif
#if WAV_RECONSTRUCT
	FILE* fout;
#endif

	int j;
	char path_buffer[_MAX_PATH];
	char fname[_MAX_PATH];
	char drive[_MAX_DRIVE];
	char dir[_MAX_DIR];
	char ext[_MAX_EXT];

	printf("%s\n", name);

	if(NULL == (fin = fopen(name, "rb")))
	{
		perror("open file for read");
		exit(1);
	}

    if(0 == GetFullPathName(name,sizeof(path_buffer),path_buffer,NULL))
    {
        printf ("GetFullPathName failed (%d)\n", GetLastError());
		exit(1);
    }

	_splitpath(path_buffer, drive, dir, fname, ext);

	_makepath( path_buffer, drive, dir, fname, "afp" );
	if(NULL == (fbin = fopen(path_buffer, "wb")))
	{
		perror("open file for write");
		exit(1);
	}

#if TXT_RECORD
	_makepath( path_buffer, drive, dir, fname, "txt" );
	if(NULL == (ftxt = fopen(path_buffer, "wt")))
	{
		perror("open file for write");
		exit(1);
	}
#endif

#if WAV_RECONSTRUCT
	strcat(fname,"_");
	_makepath( path_buffer, drive, dir, fname, "wav" );
	if(NULL == (fout = fopen(path_buffer, "wb")))
	{
		perror("open file for write");
		exit(1);
	}
#endif

	if( sizeof(WAVE) != fread(&wave, 1, sizeof(WAVE), fin) )
	{
		perror("can not read header");
		exit(1);
	}

	if(	('FFIR' != wave.ChunkID) || ('EVAW' != wave.Format) || (' tmf' != wave.SubChunk1ID) || ('atad' != wave.SubChunk2ID))
	{
		printf("Wrong format\n");
		exit(1);
	}

	if((1 != wave.NumChannels) || (16 != wave.BitsPerSample) || (1 != wave.AudioFormat))
	{
		printf("Wrong sample format\n\n");

		printf("Sample rate %d, ", wave.SampleRate);
		printf("Number of channels %d, ", wave.NumChannels);
		printf("Bits per sample %d, ", wave.BitsPerSample);
		printf("Audio format %d\n", wave.AudioFormat);

		exit(1);
	}

#if WAV_RECONSTRUCT
	if( sizeof(WAVE) != fwrite(&wave, 1, sizeof(WAVE), fout) )
	{
		perror("can not write header");
		exit(1);
	}
#endif

	//HanningWindow(win, SG_INOUT_SIZE*SG_WINDOW_OVERLAP);
	//RectangularWindow(win, SG_INOUT_SIZE*SG_WINDOW_OVERLAP);

	memset(buff_forward, 0, sizeof(buff_forward));
#if WAV_RECONSTRUCT
	memset(buff_backward, 0, sizeof(buff_backward));
#endif

	resetSpectrogram(&spectrogram);

	for(j = 0;; ++j)
//	for(j = 0; j < 256; ++j) // DEBUG !!!! for faster recognition
	{
		if(SG_INOUT_SIZE != fread(bufIn, sizeof(__int16), SG_INOUT_SIZE, fin))
		{
			break;
		}

		//forwardFFTRun(bufIn, bufProc, buff_forward, win, SG_INOUT_SIZE, SG_WINDOW_OVERLAP);
		forwardFFTRun(bufIn, bufProc, buff_forward, NULL, SG_INOUT_SIZE, SG_WINDOW_OVERLAP);
		runSpectrogram(&spectrogram, bufProc);

		fwrite(spectrogram.mBin, sizeof(__int8), SG_MAX, fbin);

#if TXT_RECORD
		for(i = 0; i < SG_MAX; ++i)
		{
			__int16 bin = spectrogram.mBin[i];
			if(255 == bin)
			{
				fprintf(ftxt, " . ");
			}
			else
			{
				fprintf(ftxt, "%2d ", bin);
			}
		}
		fprintf(ftxt, "\n");
#endif

#if WAV_RECONSTRUCT
		backwardFFTRun(bufProc, bufOut, buff_backward, SG_INOUT_SIZE, SG_WINDOW_OVERLAP);
		fwrite(bufOut, sizeof(__int16), SG_INOUT_SIZE, fout);
#endif
	}

	fclose(fbin);

#if WAV_RECONSTRUCT
	wave.SubChunk2Size = SG_INOUT_SIZE*2 * j;
	wave.ChunkSize = wave.SubChunk2Size + 36;
	fseek(fout, 0, SEEK_SET);
	fwrite(&wave, 1, sizeof(WAVE), fout);
	fclose(fout);
#endif

#if TXT_RECORD
	fclose(ftxt);
#endif
}
